import {ElMessage, ElMessageBox} from 'element-plus';
import router from '@/router';

//象棋规则类
class Rule {
    constructor(opts) {
        this.init(opts);
    }

    //初始化
    init(opts) {
        this.opts = opts;
    }

    //检查是否可走棋
    check(currentSelectChessIndex, selectIndex, position, callback) {
        this.checkCallback = callback;//检查结束回调事件
        const {chessList} = this.opts;
        const distance = this.getDistance(currentSelectChessIndex, selectIndex, position);
        if (!distance) {
            return;
        }
        //判断当前棋子类型
        const currentChess = chessList[currentSelectChessIndex];
        switch (currentChess.type) {
            case 1:
                this.checkKing(distance, currentSelectChessIndex, selectIndex, position);
                break;
            case 2:
                this.checkBachelor(distance, currentSelectChessIndex, selectIndex, position);
                break;
            case 3:
                this.checkElephant(distance, currentSelectChessIndex, selectIndex, position);
                break;
            case 4:
                this.checkHorse(distance, currentSelectChessIndex, selectIndex, position);
                break;
            case 5:
                this.checkCar(distance, currentSelectChessIndex, selectIndex, position);
                break;
            case 6:
                this.checkBigGun(distance, currentSelectChessIndex, selectIndex, position);
                break;
            case 7:
                this.checkSoldier(distance, currentSelectChessIndex, selectIndex, position);
                break;
        }
    }

    //获取两子之间的距离
    getDistance(currentSelectChessIndex, selectIndex, position) {
        const {chessList} = this.opts;
        const currentChess = chessList[currentSelectChessIndex];
        let xDistance = 0;
        let yDistance = 0;
        //判断下一步是否有棋子占位
        if (selectIndex > -1) {//有棋子
            const nextChess = chessList[selectIndex];
            if (currentChess.camp === nextChess.camp) {//如果下一步是己方棋子则不能走
                ElMessage({
                    showClose: false,
                    message: '己方棋子不能走',
                    type: 'error',
                });
                return false;
            }
            xDistance = nextChess.x - currentChess.x;
            yDistance = nextChess.y - currentChess.y;
        } else {//无棋子
            //走动距离
            xDistance = position.x - currentChess.x;
            yDistance = position.y - currentChess.y;
        }
        return {xDistance, yDistance};
    }

    //兵（卒）规则
    checkSoldier(distance, currentSelectChessIndex, selectIndex) {
        const {chessList} = this.opts;
        let currentChess = chessList[currentSelectChessIndex];
        let {xDistance, yDistance} = distance;
        //判断是否往后退
        if (yDistance > 0) {
            ElMessage({
                showClose: false,
                message: '不能往后走',
                type: 'error',
            });
            return;
        }
        //未过河前不能左、右行走
        if (currentChess.y > 4) {
            if (xDistance !== 0) {
                ElMessage({
                    showClose: false,
                    message: '过河前不能左、右行走',
                    type: 'error',
                });
                return;
            }
        }
        if (Math.abs(xDistance) > 1 || Math.abs(yDistance) > 1 || (Math.abs(xDistance) === Math.abs(yDistance))) {
            ElMessage({
                showClose: false,
                message: '每次只能走一步',
                type: 'error',
            });
            return;
        }
        this.changeChessList(currentSelectChessIndex, selectIndex, chessList, distance);
    }

    //炮规则
    checkBigGun(distance, currentSelectChessIndex, selectIndex, position) {
        const {chessList} = this.opts;
        const currentChess = chessList[currentSelectChessIndex];
        let {xDistance, yDistance} = distance;
        if (xDistance !== 0 && yDistance !== 0) {
            ElMessage({
                showClose: false,
                message: '只能直线行走',
                type: 'error',
            });
            return;
        }

        if (selectIndex > -1) {//有棋子
            if (Math.abs(xDistance) > 0) {
                let start = xDistance > 0 ? currentChess.x : position.x;
                let end = xDistance > 0 ? position.x : currentChess.x;
                let check = chessList.filter((item) => {
                    if (item.active && item.y === currentChess.y && item.x > start && item.x < end) {
                        return true;
                    }
                });
                if (check.length !== 1) {
                    ElMessage({
                        showClose: false,
                        message: '中间有一个棋子才能走',
                        type: 'error',
                    });
                    return;
                }
            }

            if (Math.abs(yDistance) > 0) {
                let start = yDistance > 0 ? currentChess.y : position.y;
                let end = yDistance > 0 ? position.y : currentChess.y;
                let check = chessList.filter((item) => {
                    if (item.active && item.x === currentChess.x && item.y > start && item.y < end) {
                        return true;
                    }
                });
                if (check.length !== 1) {
                    ElMessage({
                        showClose: false,
                        message: '中间有一个棋子才能走',
                        type: 'error',
                    });
                    return;
                }
            }
        } else {
            if (Math.abs(xDistance) > 0) {
                let start = xDistance > 0 ? currentChess.x : position.x;
                let end = xDistance > 0 ? position.x : currentChess.x;
                let check = chessList.some((item) => {
                    if (item.active && item.y === currentChess.y && item.x > start && item.x < end) {
                        return true;
                    }
                });
                if (check) {
                    ElMessage({
                        showClose: false,
                        message: '中间有棋子不能走',
                        type: 'error',
                    });
                    return;
                }
            }

            if (Math.abs(yDistance) > 0) {
                let start = yDistance > 0 ? currentChess.y : position.y;
                let end = yDistance > 0 ? position.y : currentChess.y;
                let check = chessList.some((item) => {
                    if (item.active && item.x === currentChess.x && item.y > start && item.y < end) {
                        return true;
                    }
                });
                if (check) {
                    ElMessage({
                        showClose: false,
                        message: '中间有棋子不能走',
                        type: 'error',
                    });
                    return;
                }
            }
        }
        this.changeChessList(currentSelectChessIndex, selectIndex, chessList, distance);
    }

    //車规则
    checkCar(distance, currentSelectChessIndex, selectIndex, position) {
        const {chessList} = this.opts;
        const currentChess = chessList[currentSelectChessIndex];
        let {xDistance, yDistance} = distance;
        if (xDistance !== 0 && yDistance !== 0) {
            ElMessage({
                showClose: false,
                message: '只能直线行走',
                type: 'error',
            });
            return;
        }

        if (Math.abs(xDistance) > 0) {
            let start = xDistance > 0 ? currentChess.x : position.x;
            let end = xDistance > 0 ? position.x : currentChess.x;
            let check = chessList.some((item) => {
                if (item.active && item.y === currentChess.y && item.x > start && item.x < end) {
                    return true;
                }
            });
            if (check) {
                ElMessage({
                    showClose: false,
                    message: '中间有棋子不能走',
                    type: 'error',
                });
                return;
            }
        }

        if (Math.abs(yDistance) > 0) {
            let start = yDistance > 0 ? currentChess.y : position.y;
            let end = yDistance > 0 ? position.y : currentChess.y;
            let check = chessList.some((item) => {
                if (item.active && item.x === currentChess.x && item.y > start && item.y < end) {
                    return true;
                }
            });
            if (check) {
                ElMessage({
                    showClose: false,
                    message: '中间有棋子不能走',
                    type: 'error',
                });
                return;
            }
        }
        this.changeChessList(currentSelectChessIndex, selectIndex, chessList, distance);
    }

    //馬规则
    checkHorse(distance, currentSelectChessIndex, selectIndex) {
        const {chessList} = this.opts;
        const currentChess = chessList[currentSelectChessIndex];
        let {xDistance, yDistance} = distance;
        if (!((Math.abs(xDistance) === 2 && Math.abs(yDistance) === 1) || (Math.abs(xDistance) === 1 && Math.abs(yDistance) === 2))) {
            ElMessage({
                showClose: false,
                message: '需要走日字',
                type: 'error',
            });
            return;
        }

        if (Math.abs(xDistance) > Math.abs(yDistance)) {
            let start = xDistance > 0 ? currentChess.x : currentChess.x + xDistance;
            let end = xDistance > 0 ? currentChess.x + xDistance : currentChess.x;
            let check = chessList.some((item) => {
                if (item.active && currentChess.y === item.y && item.x > start && item.x < end) {
                    return true;
                }
            });
            if (check) {
                ElMessage({
                    showClose: false,
                    message: '马脚有棋子不能走',
                    type: 'error',
                });
                return;
            }
        } else {
            let start = yDistance > 0 ? currentChess.y : currentChess.y + yDistance;
            let end = yDistance > 0 ? currentChess.y + yDistance : currentChess.y;
            let check = chessList.some((item) => {
                if (item.active && currentChess.x === item.x && item.y > start && item.y < end) {
                    return true;
                }
            });
            if (check) {
                ElMessage({
                    showClose: false,
                    message: '马脚有棋子不能走',
                    type: 'error',
                });
                return;
            }
        }
        this.changeChessList(currentSelectChessIndex, selectIndex, chessList, distance);
    }

    //象规则
    checkElephant(distance, currentSelectChessIndex, selectIndex, position) {
        const {chessList} = this.opts;
        const currentChess = chessList[currentSelectChessIndex];
        let {xDistance, yDistance} = distance;
        if (selectIndex > -1) {
            const nextChess = chessList[selectIndex];
            if (nextChess.y < 5) {
                ElMessage({
                    showClose: false,
                    message: '象不能过河',
                    type: 'error',
                });
                return;
            }
        } else {
            if (position.y < 5) {
                ElMessage({
                    showClose: false,
                    message: '象不能过河',
                    type: 'error',
                });
                return;
            }
        }

        if (Math.abs(xDistance) !== 2 || Math.abs(yDistance) !== 2) {
            ElMessage({
                showClose: false,
                message: '需要走田字',
                type: 'error',
            });
            return;
        }

        let x = currentChess.x + xDistance / 2;
        let y = currentChess.y + yDistance / 2;

        let check = chessList.some((item) => {
            if (item.active && item.x === x && item.y === y) {
                return true;
            }
        });
        if (check) {
            ElMessage({
                showClose: false,
                message: '中间有棋子不能走',
                type: 'error',
            });
            return;
        }
        this.changeChessList(currentSelectChessIndex, selectIndex, chessList, distance);
    }

    //士规则
    checkBachelor(distance, currentSelectChessIndex, selectIndex, position) {
        const {chessList} = this.opts;
        let {xDistance, yDistance} = distance;
        if (Math.abs(xDistance) !== 1 || Math.abs(yDistance) !== 1) {
            ElMessage({
                showClose: false,
                message: '需要走口字',
                type: 'error',
            });
            return false;
        }

        let x = 0, y = 0;
        if (selectIndex > -1) {
            const nextChess = chessList[selectIndex];
            x = nextChess.x;
            y = nextChess.y;
        } else {
            x = position.x;
            y = position.y;
        }
        //目标位置不能超出边界
        if (x < 3 || x > 5 || y < 7) {
            ElMessage({
                showClose: false,
                message: '不能超出边界',
                type: 'error',
            });
            return false;
        }

        this.changeChessList(currentSelectChessIndex, selectIndex, chessList, distance);

    }

    //将（帥）规则
    checkKing(distance, currentSelectChessIndex, selectIndex, position) {
        const {chessList} = this.opts;
        let {xDistance, yDistance} = distance;
        if (!((Math.abs(xDistance) === 1 && Math.abs(yDistance) === 0) || (Math.abs(xDistance) === 0 && Math.abs(yDistance) === 1))) {
            ElMessage({
                showClose: false,
                message: '每次只能走一步',
                type: 'error',
            });
            return;
        }

        let x = 0, y = 0;
        if (selectIndex > -1) {
            const nextChess = chessList[selectIndex];
            x = nextChess.x;
            y = nextChess.y;
        } else {
            x = position.x;
            y = position.y;
        }
        //目标位置不能超出边界
        if (x < 3 || x > 5 || y < 7) {
            ElMessage({
                showClose: false,
                message: '不能超出边界',
                type: 'error',
            });
            return;
        }
        this.changeChessList(currentSelectChessIndex, selectIndex, chessList, distance);
    }

    //修改棋子列表
    changeChessList(currentSelectChessIndex, selectIndex, chessList, distance) {
        const checkCallback = this.checkCallback;
        let {xDistance, yDistance} = distance;
        chessList[currentSelectChessIndex].x = chessList[currentSelectChessIndex].x + xDistance;
        chessList[currentSelectChessIndex].y = chessList[currentSelectChessIndex].y + yDistance;
        chessList[currentSelectChessIndex].select = false;
        if (selectIndex > -1) {//有棋子
            chessList[selectIndex].active = false;
            let check = Rule.checkIsKing(chessList[selectIndex].type);
            if (check) {
                checkCallback && checkCallback({
                    isFinish: true,
                    winner: chessList[currentSelectChessIndex].camp,
                    looser: chessList[selectIndex].camp,
                    currentSelectChessIndex,
                    xDistance,
                    yDistance,
                    selectIndex
                });
                return;
            }
        }
        let check = this.checkIsKingToKing(chessList);
        if (check) {
            checkCallback && checkCallback({
                isFinish: true,
                winner: chessList[currentSelectChessIndex].camp === 1 ? 2 : 1,
                looser: chessList[currentSelectChessIndex].camp,
                currentSelectChessIndex,
                xDistance,
                yDistance,
                selectIndex
            });
        } else {
            checkCallback && checkCallback({
                isFinish: false,
                currentSelectChessIndex,
                xDistance,
                yDistance,
                selectIndex
            });
        }
    }

    //判断是否是king
    static checkIsKing(type) {
        if (type === 1) {
            ElMessageBox.alert('恭喜你赢了', '比赛结果', {
                type: 'success',
                confirmButtonText: 'OK',
                async callback() {
                    await router.back();
                }
            });
            return true;
        }
        return false;
    }

    //判断是否王见王
    checkIsKingToKing(chessList) {
        let chess1 = null, chess2 = null;
        chessList.forEach((item) => {
            if (item.type === 1 && item.camp === 1) {
                chess1 = item;
            }
            if (item.type === 1 && item.camp === 2) {
                chess2 = item;
            }
        });
        if (chess1.x === chess2.x) {
            let check = chessList.some((item) => {
                if (item.active && item.type !== 1 && item.x === chess1.x) {
                    return true;
                }
            });
            if (!check) {
                ElMessageBox.alert('很遗憾你输了', '比赛结果', {
                    type: 'fail',
                    confirmButtonText: 'OK',
                    async callback() {
                        await router.back();
                    }
                });
                return true;
            }
        }
        return false;
    }
}

export default Rule;